/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package executingimpl.runner;

import executing.AbstractProcessRunner;
import executing.ExecutionResultFactory;
import executing.IProcessRunner;
import executor.ExecutionResult;
import java.io.*;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author ryuju
 */
public class ExecuteProcessRunner extends AbstractProcessRunner {

    @Override
    public ExecutionResult run(List<String> cmdList, String input) {
        
        ExecutionResult execResult = ExecutionResultFactory.getEmptyExecutionResult();
        ProcessBuilder pb = new ProcessBuilder(cmdList);
        Process process = null;

        try {
            process = pb.start();
        } catch (IOException ex) {
            execResult.errOccured = true;
            execResult.errMsg = ex.getMessage();
            Logger.getLogger(ExecuteProcessRunner.class.getName()).log(Level.SEVERE, null, ex);
            return execResult;
        }

        StringWriter stdOut = new StringWriter();
        StringWriter stdErr = new StringWriter();

        BufferedInputStream outStm = new BufferedInputStream(process.getInputStream());
        BufferedInputStream errStm = new BufferedInputStream(process.getErrorStream());
        BufferedWriter inWriter = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
        
        try {

            // writer input to buffer.
            if (null != input) {
                inWriter.write(input + "\n");
                inWriter.flush();
            }
            long startTime = System.currentTimeMillis();
            boolean isEnd = false;
            while (false == isEnd) {
                Thread.sleep(10);
                boolean blockMode = false;
                try {
                    process.exitValue();
                    blockMode = true;
                } catch (IllegalThreadStateException e) {
                    // nothing
                }

                int readStdOut = readStream(outStm, stdOut, blockMode);
                int readStdErr = readStream(errStm, stdErr, blockMode);

                if (0 > readStdOut && 0 > readStdErr) {
                    isEnd = true;
                }
            }
            execResult.exitCode = process.waitFor();
            execResult.execCompleted = true;
            execResult.execTime = (int)(System.currentTimeMillis() - startTime);
        } catch (Exception e) {
            execResult.errMsg += e.getMessage();
            execResult.errOccured = true;
            
        } finally {
            try {
                outStm.close();
                errStm.close();
                inWriter.close();
                process.getErrorStream().close();
                process.getOutputStream().close();
                process.getInputStream().close();
            } catch (Exception e) {
                execResult.errMsg += e.getMessage();
                execResult.errOccured = true;
            }

        }
        
        execResult.errMsg = stdErr.toString();
        String[] outputs = new String[1];
        outputs[0] = stdOut.toString();
        execResult.outputs = outputs;

        return execResult;
    }
}
